const mysql = require('../db/mysql57');

const loginService = require("../service/login");
const hospitalService = require("../service/hospital");
const userService = require("../service/user");
const devService = require("../service/dev");
const washService = require("../service/wash");
const faultService = require('../service/fault');
const repairService = require('../service/repair');

const Response = require('../entity/http/Response');

/*
 * 这个权限机制拦截的时候需要用到 用户的主键 uid 目前并没有实现这一步 后续思考是从全局状态里拿这个值还是直接通过参数传递
 * 暂时使用参数传递的方式 待完善 后期可以使用依赖注入的设计模式 但相对来说会稍微复杂一点 本项目只采用 参数传递的方式即可
 * 目前规定所有的 Service 接口都统一参数为 [ reqId, uid, <其他数据参数> ]
 */

/**
 * @name powerMap 权限控制机制
 * @connect service -> power
 * @desc 拦截所有service的调用 由Proxy接管 遍历power数组查看所有需要的权限 并且逐一验证
 */
const powerMap = {
    // Login 登录模块
    'loginService.login': {
        power: [],
        function: loginService.login,
        parent: loginService,
        name: 'login'
    },
    // User 用户模块
    'userService.getSelfInfo': {
        power: [],
        function: userService.getSelfInfo,
        parent: userService,
        name: 'getSelfInfo'
    },
    'userService.getUserInfo': {
        power: [ 'user.getUser' ],
        function: userService.getUserInfo,
        parent: userService,
        name: 'getUserInfo'
    },
    'userService.getUserInfoAndPassword': {
        power: [ 'user.getUser', 'user.getUserPassword' ],
        function: userService.getUserInfoAndPassword,
        parent: userService,
        name: 'getUserInfoAndPassword'
    },
    'userService.register': {
        power: [ 'user.addUser' ],
        function: userService.register,
        parent: userService,
        name: 'register'
    },
    'userService.getPower': {
        power: [],
        function: userService.getPower,
        parent: userService,
        name: 'getPower'
    },
    'userService.getAllUser': {
        power: [ 'user.getUser' ],
        function: userService.getAllUser,
        parent: userService,
        name: 'getAllUser'
    },
    'userService.getAllUserAndPassword': {
        power: [ 'user.getUser', 'user.getUserPassword' ],
        function: userService.getAllUserAndPassword,
        parent: userService,
        name: 'getAllUserAndPassword'
    },
    'userService.deleteUser': {
        power: [ 'user.delUser' ],
        function: userService.deleteUser,
        parent: userService,
        name: 'deleteUser'
    },
    'userService.updateUserInfo': {
        power: [ 'user.updateUser' ],
        function: userService.updateUserInfo,
        parent: userService,
        name: 'updateUserInfo'
    },
    'userService.updateUserInfoAndPassword': {
        power: [ 'user.updateUser', 'user.updateUserPassword' ],
        function: userService.updateUserInfoAndPassword,
        parent: userService,
        name: 'updateUserInfoAndPassword'
    },
    'userService.updateSelfInfoAndPassword': {
        power: [],
        function: userService.updateSelfInfoAndPassword,
        parent: userService,
        name: 'updateSelfInfoAndPassword'
    },
    'userService.getUserDepartment': {
        power: [ 'user.getUser', 'department.getDepartment' ],
        function: userService.getUserDepartment,
        parent: userService,
        name: 'getUserDepartment'
    },
    'userService.getSelfDepartment': {
        power: [],
        function: userService.getSelfDepartment,
        parent: userService,
        name: 'getSelfDepartment'
    },
    'userService.getSelfPowerList': {
        power: [],
        function: userService.getSelfPowerList,
        parent: userService,
        name: 'getSelfPowerList'
    },
    // Hospital 医院科室模块
    'hospitalService.addHospitalAndAdmin': {
        power: [ 'user.addUser', 'department.addDepartment' ],
        function: hospitalService.addHospitalAndAdmin,
        parent: hospitalService,
        name: 'addHospitalAndAdmin'
    },
    'hospitalService.addHospital': {
        power: [ 'department.addDepartment' ],
        function: hospitalService.addHospital,
        parent: hospitalService,
        name: 'addHospital'
    },
    'hospitalService.delHospital': {
        power: [ 'department.delDepartment' ],
        function: hospitalService.delHospital,
        parent: hospitalService,
        name: 'delHospital'
    },
    'hospitalService.changeHospital': {
        power: [ 'department.changeDepartment' ],
        function: hospitalService.changeHospital,
        parent: hospitalService,
        name: 'changeHospital'
    },
    'hospitalService.getHospital': {
        power: [ 'department.getDepartment' ],
        function: hospitalService.getHospital,
        parent: hospitalService,
        name: 'getHospital'
    },
    'hospitalService.getAllHospital': {
        power: [ 'department.getDepartment' ],
        function: hospitalService.getAllHospital,
        parent: hospitalService,
        name: 'getAllHospital'
    },
    'hospitalService.getAllDevice': {
        power: [ 'department.getDepartment' ],
        function: hospitalService.getAllDevice,
        parent: hospitalService,
        name: 'getAllDevice'
    },
    // device 设备模块
    'devService.addArgvVersion': {
        power: [ 'dev.addArgvVersion' ],
        function: devService.addArgvVersion,
        parent: devService,
        name: 'addArgvVersion'
    },
    'devService.getAllArgvVersion': {
        power: [ 'dev.getArgvVersion' ],
        function: devService.getAllArgvVersion,
        parent: devService,
        name: 'getAllArgvVersion'
    },
    'devService.getArgvVersionInfo': {
        power: [ 'dev.getArgvVersion' ],
        function: devService.getArgvVersionInfo,
        parent: devService,
        name: 'getArgvVersionInfo'
    },
    'devService.copyCreateArgvVersion': {
        power: [ 'dev.addArgvVersion' ],
        function: devService.copyCreateArgvVersion,
        parent: devService,
        name: 'copyCreateArgvVersion'
    },
    'devService.getArgvVersionUsed': {
        power: [ 'dev.getArgvVersion', 'dev.getDev' ],
        function: devService.getArgvVersionUsed,
        parent: devService,
        name: 'getArgvVersionUsed'
    },
    'devService.deleteArgvVersion': {
        power: [ 'dev.delArgvVersion' ],
        function: devService.deleteArgvVersion,
        parent: devService,
        name: 'deleteArgvVersion'
    },
    'devService.updateArgvVersion': {
        power: [ 'dev.updateArgvVersion' ],
        function: devService.updateArgvVersion,
        parent: devService,
        name: 'updateArgvVersion'
    },
    'devService.addDevType': {
        power: [ 'dev.addDevType' ],
        function: devService.addDevType,
        parent: devService,
        name: 'addDevType'
    },
    'devService.getAllDevType': {
        power: [ 'dev.getDevType' ],
        function: devService.getAllDevType,
        parent: devService,
        name: 'getAllDevType'
    },
    'devService.updateDevType': {
        power: [ 'dev.updateDevType' ],
        function: devService.updateDevType,
        parent: devService,
        name: 'updateDevType'
    },
    'devService.getDevTypeUsed': {
        power: [ 'dev.getDevType', 'dev.getDev' ],
        function: devService.getDevTypeUsed,
        parent: devService,
        name: 'getDevTypeUsed'
    },
    'devService.deleteDevType': {
        power: [ 'dev.delDevType' ],
        function: devService.deleteDevType,
        parent: devService,
        name: 'deleteDevType'
    },
    'devService.addDevice': {
        power: [ 'dev.addDev' ],
        function: devService.addDevice,
        parent: devService,
        name: 'addDevice'
    },
    'devService.getDeviceList': {
        power: [ 'dev.getDev' ],
        function: devService.getDeviceList,
        parent: devService,
        name: 'getDeviceList'
    },
    'devService.getDeviceInfo': {
        power: [ 'dev.getDev' ],
        function: devService.getDeviceInfo,
        parent: devService,
        name: 'getDeviceInfo'
    },
    'devService.deleteDevice': {
        power: [ 'dev.delDev' ],
        function: devService.deleteDevice,
        parent: devService,
        name: 'deleteDevice'
    },
    'devService.getDeviceArgv': {
        power: [ 'dev.getDev' ],
        function: devService.getDeviceArgv,
        parent: devService,
        name: 'getDeviceArgv'
    },
    'devService.ctrlReadArgv': {
        power: [ 'dev.ctrlDev' ],
        function: devService.ctrlReadArgv,
        parent: devService,
        name: 'ctrlReadArgv'
    },
    'devService.ctrlSetStatus': {
        power: [ 'dev.ctrlDev' ],
        function: devService.ctrlSetStatus,
        parent: devService,
        name: 'ctrlSetStatus'
    },
    'devService.ctrlSetPassword': {
        power: [ 'dev.ctrlDev' ],
        function: devService.ctrlSetPassword,
        parent: devService,
        name: 'ctrlSetPassword'
    },
    'devService.ctrlCancel': {
        power: [ 'dev.ctrlDev' ],
        function: devService.ctrlCancel,
        parent: devService,
        name: 'ctrlCancel'
    },
    'devService.updateDevDepartment': {
        power: [ 'dev.updateDev' ],
        function: devService.updateDevDepartment,
        parent: devService,
        name: 'updateDevDepartment'
    },
    'devService.updateDevInfo': {
        power: [ 'dev.updateDev' ],
        function: devService.updateDevInfo,
        parent: devService,
        name: 'updateDevInfo'
    },
    'devService.updateOpenRate': {
        power: [ 'dev.updateOpenRate' ],
        function: devService.updateOpenRate,
        parent: devService,
        name: 'updateOpenRate'
    },
    // wash 洗消管理模块
    'washService.getAllWashRecord': {
        power: [ 'wash.getWashRecord' ],
        function: washService.getAllWashRecord,
        parent: washService,
        name: 'getAllWashRecord'
    },
    'washService.getWashRecordInfo': {
        power: [ 'wash.getWashRecord' ],
        function: washService.getWashRecordInfo,
        parent: washService,
        name: 'getWashRecordInfo'
    },
    'washService.updateWashRecord': {
        power: [ 'wash.updateWashRecord' ],
        function: washService.updateWashRecord,
        parent: washService,
        name: 'updateWashRecord'
    },
    'washService.delWashRecordInfo': {
        power: [ 'wash.delWashRecord' ],
        function: washService.delWashRecordInfo,
        parent: washService,
        name: 'delWashRecordInfo'
    },
    // fault 故障管理模块
    'faultService.getAllfault': {
        power: [ 'fault.getFault' ],
        function: faultService.getAllfault,
        parent: faultService,
        name: 'getAllfault'
    },
    'faultService.deletefault': {
        power: [ 'fault.delFault' ],
        function: faultService.deletefault,
        parent: faultService,
        name: 'deletefault'
    },
    'faultService.readFault': {
        power: [ 'fault.readFault' ],
        function: faultService.readFault,
        parent: faultService,
        name: 'readFault'
    },
    // repair 维修管理模块
    'repairService.addRepair': {
        power: [ 'repair.addRepair' ],
        function: repairService.addRepair,
        parent: repairService,
        name: 'addRepair'
    },
    'repairService.getAllRepair': {
        power: [ 'repair.getRepair' ],
        function: repairService.getAllRepair,
        parent: repairService,
        name: 'getAllRepair'
    },
    'repairService.updateRepair': {
        power: [ 'repair.updateRepair' ],
        function: repairService.updateRepair,
        parent: repairService,
        name: 'updateRepair'
    },
    'repairService.deleteRepair': {
        power: [ 'repair.delRepair' ],
        function: repairService.deleteRepair,
        parent: repairService,
        name: 'deleteRepair'
    },
};

// 权限统一拦截
(function () {
    for (let key in powerMap) {
        let value = powerMap[key];
        // 拦截逻辑
        let proxy = new Proxy(value.function, {
            async apply(target, thisArg, argumentsList) {
                let reqId = argumentsList[0];   // 从传递的参数中获取请求id
                let uid = argumentsList[1];     // 从传递的参数中获取用户id
                console.log(`[ INFO ] [ req-id = ${ reqId } ] [ Power ] 进入权限拦截验证`);
                // 验证权限的逻辑
                for (let i = 0; i < value.power.length; i++) {
                    console.log(`[ POWER ] [ req-id = ${ reqId } ] [ Power ] 验证权限 ${ value.power[i] }`);
                    let sql = `select id from UserPower where userId = ? and powerId = (
                            select id from Power where name = ?
                        )`;
                    let data = [ uid, value.power[i] ];
                    let dbResult = await mysql.sqlExec(sql, data);
                    if (dbResult.length === 0) {
                        console.log(`[ POWER ] [ req-id = ${ reqId } ] [ Power ] 权限 ${ value.power[i] } 不通过 用户 [ uid = ${ uid } ] 不具备该权限`);
                        return new Response().fail(403, "权限不足");
                    }
                    console.log(`[ POWER ] [ req-id = ${ reqId } ] [ Power ] 权限 ${ value.power[i] } 验证通过`);
                }
                console.log(`[ INFO ] [ req-id = ${ reqId } ] [ Power ] 权限拦截验证通过`);
                let ret = Reflect.apply(...arguments);
                return ret;
            }
        });
        // 装饰器函数
        value.parent[value.name] = proxy;
    }
})();

module.exports = powerMap;